package com.tdk.common.util

/**
 * @author carverLee
 * 2019/7/22 14:27
 */
object CollectionUtils {
    /**
     * find item from src collection,if multiple data matched,return the first one
     *
     * @param data  src data collection
     * @param query query
     * @param <T>   data type
     * @return first target item
    </T> */
    fun <T> findItem(data: Collection<T>?, query: (T) -> Boolean): T? {
        if (data.isNullOrEmpty()) {
            return null
        }
        for (item in data) {
            if (item == null) {
                continue
            }
            if (query.invoke(item)) {
                return item
            }
        }
        return null
    }

    /**
     * find item list in collection
     *
     * @param data  src data collection
     * @param query query
     * @param <T>   data  type
     * @return target item list
    </T> */
    fun <T> findItemList(data: Collection<T>?, query: Query<T>): List<T> {
        val result: MutableList<T> = ArrayList()
        if (data.isNullOrEmpty()) {
            return result
        }
        for (item in data) {
            if (item == null) {
                continue
            }
            if (query.match(item)) {
                result.add(item)
            }
        }
        return result
    }

    /**
     * do same action for a collection
     *
     * @param data   src data collection
     * @param action action
     * @param <T>    data type
    </T> */
    fun <T> doForEach(data: Collection<T>?, action: Action<T>) {
        if (data.isNullOrEmpty()) {
            return
        }
        for (item in data) {
            if (item != null) {
                action.action(item)
            }
        }
    }

    /**
     * copy items from src collection to dest collection by filter
     *
     * @param src    src data collection
     * @param dest   target collection
     * @param filter filter
     * @param <T>    data type
    </T> */
    fun <T> copy(src: Collection<T>?, dest: MutableCollection<T>?, filter: Query<T>?) {
        if (src.isNullOrEmpty() || dest == null) {
            return
        }
        for (item in src) {
            if (filter == null || filter.match(item)) {
                dest.add(item)
            }
        }
    }

    interface Query<T> {
        fun match(data: T): Boolean
    }

    interface Action<T> {
        fun action(data: T)
    }
}